import { _decorator, AnimationComponent, Component, find, Node, ParticleSystemComponent, Prefab, Vec3 } from 'cc';
import { resourceUtil } from './resourceUtil';
import { poolManager } from './poolManager';
import { reward } from '../fight/reward';
import { warningLine } from '../fight/warningSkill/warningLine';
const { ccclass, property } = _decorator;

@ccclass('effectManager')
export class effectManager extends Component {

    private _ndParent: Node = null!;
    public get ndParent() {
        if (!this._ndParent) {
            this._ndParent = find("effectManager") as Node;
        }

        return this._ndParent
    }

    static _instance: effectManager;

    static get instance() {
        if (this._instance) {
            return this._instance;
        }

        this._instance = new effectManager();
        return this._instance;
    }

    /**
     * 展示奖励(金币、爱心)弹跳
     *
     * @param {Node} ndMonster
     * @param {string} modelPath
     * @param {number} [rewardNum=1]
     * @param {Function} [callback=()=>{}]
     * @memberof EffectManager
     */
    public showRewardBounce(ndMonster: Node, modelPath: string, rewardNum: number = 1, callback: Function = () => { }) {
        resourceUtil.loadModelRes(modelPath).then((pf: any) => {
            for (let i = 0; i < rewardNum; i++) {
                let ndReward = poolManager.instance.getNode(pf, this.ndParent) as Node;
                ndReward.setWorldPosition(ndMonster.worldPosition.x, 1.65, ndMonster.worldPosition.z);
                ndReward.active = false;
                let scriptReward = ndReward.getComponent(reward) as reward;
                scriptReward.init((i + 1) * 0.15, this.ndParent);
            }

            callback && callback();
        });
    }

    /**
     * 播放拖尾特效
     *
     * @param {Node} ndParent
     * @memberof effectManager
     */
    public playTrail(ndParent: Node, recycleTime: number = 0, callback?: Function, speed: number = 1) {
        let maxDuration: number = 0;

        let arrParticle: ParticleSystemComponent[] = ndParent.getComponentsInChildren(ParticleSystemComponent);
        arrParticle.forEach((element: ParticleSystemComponent) => {
            element.simulationSpeed = speed;
            element?.clear();
            element?.stop();
            element?.play();

            let duration: number = element.duration;
            maxDuration = duration > maxDuration ? duration : maxDuration;
        })

        let seconds: number = recycleTime && recycleTime > 0 ? recycleTime : maxDuration;

        setTimeout(() => {
            callback && callback();
        }, seconds * 1000)
    }

    /**
     * 播放节点下面的动画和粒子
     *
     * @param {Node} targetNode 特效挂载节点
     * @param {string} effectPath 特效路径
     * @param {boolean} [isPlayAni=true] 是否播放动画
     * @param {boolean} [isPlayParticle=true] 是否播放特效
     * @param {number} [recycleTime=0] 特效节点回收时间，如果为0，则使用默认duration
     * @param {number} [scale=1] 缩放倍数
     * @param {Vec3} [pos=new Vec3()] 位移
     * @param {Function} [callback=()=>{}] 回调函数
     * @returns
     * @memberof EffectManager
     */
    public playEffect(targetNode: Node, effectPath: string, isPlayAni: boolean = true, isPlayParticle: boolean = true, recycleTime: number = 0, scale: number = 1, pos?: Vec3 | null, eulerAngles?: Vec3 | null, callback?: Function) {
        if (!targetNode.parent) {//父节点被回收的时候不播放
            return;
        }

        resourceUtil.loadEffectRes(effectPath).then((prefab: any) => {
            let ndEffect: Node = poolManager.instance.getNode(prefab as Prefab, targetNode) as Node;
            ndEffect.setScale(new Vec3(scale, scale, scale));

            if (pos) {
                ndEffect.setPosition(pos);
            }

            if (eulerAngles) {
                ndEffect.eulerAngles = eulerAngles;
            }

            let maxDuration: number = 0;

            if (isPlayAni) {
                let arrAni: AnimationComponent[] = ndEffect.getComponentsInChildren(AnimationComponent);

                arrAni.forEach((element: AnimationComponent, idx: number) => {
                    element?.play();

                    let aniName = element?.defaultClip?.name;
                    if (aniName) {
                        let aniState = element.getState(aniName);
                        if (aniState) {
                            let duration = aniState.duration;
                            maxDuration = duration > maxDuration ? duration : maxDuration;

                            aniState.speed = 1;
                        }
                    }
                })
            }

            if (isPlayParticle) {
                let arrParticle: ParticleSystemComponent[] = ndEffect.getComponentsInChildren(ParticleSystemComponent);
                arrParticle.forEach((element: ParticleSystemComponent) => {
                    element.simulationSpeed = 1;
                    element?.clear();
                    element?.stop();
                    element?.play()

                    let duration: number = element.duration;
                    maxDuration = duration > maxDuration ? duration : maxDuration;
                })
            }

            let seconds: number = recycleTime && recycleTime > 0 ? recycleTime : maxDuration;

            setTimeout(() => {
                if (ndEffect.parent) {
                    poolManager.instance.putNode(ndEffect);
                    callback && callback();
                }
            }, seconds * 1000)
        })
    }

    /**
     * 展示预警
     *
     * @param {string} warningName
     * @param {number} scale
     * @param {*} scriptParent
     * @memberof EffectManager
     */
    public showWarning(warningName: string, scale: number, scriptParent: any, callback?: Function) {
        resourceUtil.loadEffectRes(`warning/${warningName}`).then((pf: any) => {
            let ndWarning = poolManager.instance.getNode(pf, this.ndParent) as Node;

            let scriptWarning: any = null;
            if (warningName === "warningLine") {
                scriptWarning = ndWarning.getComponent(warningLine) as warningLine;
            } else if (warningName === "warningStrip") {
                scriptWarning = ndWarning.getComponent(warningLine) as warningLine;
            } else if (warningName === "warningCircle") {
                scriptWarning = ndWarning.getComponent(warningLine) as warningLine;
            }

            scriptWarning.init(scale, scriptParent);

            scriptParent.scriptWarning = scriptWarning;

            callback && callback();
        });
    }

}


